//工厂模式  分为：简单工厂模式，工厂方法模式和抽象工厂模式

//简单工厂模式又叫静态方法模式，因为工厂类中定义了一个静态方法用于创建对象。
//简单工厂让使用者不用知道具体参数就可以创建出所需的产品类，即使用者可以直接消费产品而不需要知道产品的具体生产细节

abstract class BMW {
  abstract run(): void;
}

class BMW730 extends BMW {
  run(): void {
    console.log("BMW730 发动");
  }
}

class BMW840 extends BMW {
  run(): void {
    console.log("BMW840 发动");
  }
}

class BWMFactory {
  public static produceBMW(mode: "730" | "840"): BMW {
    if (mode === "730") {
      return new BMW730();
    }
    if (mode === "840") {
      return new BMW840();
    }
  }
}

const bwm730 = BWMFactory.produceBMW("730");
const bwm840 = BWMFactory.produceBMW("840");

bwm730.run();
bwm840.run();

//工厂方法：工厂方法模式又称工厂模式，也叫多态工厂模式，它属于类创建型模式
//在工厂方法模式中，工厂父类负责定义创建产品对象的公共接口，而工厂子类则负责生成具体的产品对象，这样
//做的目的是将产品类的实例化操作延迟到工厂子类中完成，即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

abstract class BMWFactory {
  abstract produceBMW(): BMW;
}

class BMW730Factory extends BWMFactory {
  produceBMW(): BMW {
    return new BMW730();
  }
}

class BMW840Factory extends BMWFactory {
  produceBMW(): BMW {
    return new BMW840();
  }
}

//抽象工厂模式：提供一个创建一系列相关或相互依赖对象的接口，而无须指定它们具体的类
//在工厂方法模式中具体工厂负责生产具体的产品，每一个具体工厂对应一种具体产品，工厂方法也具有唯一性，
//一般情况下，一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个
//产品对象，而不是单一的产品对象。

abstract class BMWFactory {
  abstract produce730BMW(): BMW730;
  abstract produce840BMW(): BMW840;
}

class ConcreateBMWFactory extends BMWFactory {
  produce730BMW(): BMW730 {
    return new BMW730();
  }
  produce840BMW(): BMW840 {
    return new BMW840();
  }
}
